﻿using System;
using System.Diagnostics;
using System.IO;

//using Point = GMap.NET.Point;

namespace GMap.NET.CacheProviders
{
    class FolderPureImageCache : PureImageCache
    {
        string _pathString = string.Empty;
        public string PathString
        {
            get
            {
                return _pathString;
            }
            set
            {
                if (_pathString != value)
                {
                    _pathString = value;

                    if (Initialized)
                    {
                        //Dispose();
                        Initialize();
                    }
                }
            }
        }
        bool _initialized = false;

        /// <summary>
        /// is cache initialized
        /// </summary>
        public bool Initialized
        {
            get
            {
                lock (this)
                {
                    return _initialized;
                }
            }
            private set
            {
                lock (this)
                {
                    _initialized = value;
                }
            }
        }

        /// <summary>
        /// inits folder
        /// </summary>
        /// <returns></returns>
        public bool Initialize()
        {
            lock (this)
            {
                if (!_initialized)
                {
                    #region prepare mssql & cache table
                    try
                    {
                        // prepare general folder
                        if (!Directory.Exists(_pathString))
                        {
                            Directory.CreateDirectory(_pathString);
                        }

                        // prepare maps foldes
                        Initialized = true;
                    }
                    catch (Exception ex)
                    {
                        this._initialized = false;
                        Debug.WriteLine(ex.Message);
                    }
                    #endregion
                }
                return _initialized;
            }
        }

        #region IDisposable Members
        /*
        public void Dispose()
        {
            lock (cmdInsert)
            {
                if (cmdInsert != null)
                {
                    cmdInsert.Dispose();
                    cmdInsert = null;
                }

                if (cnSet != null)
                {
                    cnSet.Dispose();
                    cnSet = null;
                }
            }

            lock (cmdFetch)
            {
                if (cmdFetch != null)
                {
                    cmdFetch.Dispose();
                    cmdFetch = null;
                }

                if (cnGet != null)
                {
                    cnGet.Dispose();
                    cnGet = null;
                }
            }
            Initialized = false;
        }
         * */
        #endregion

        #region PureImageCache Members
        public bool PutImageToCache(MemoryStream tile, MapType type, Point pos, int zoom)
        {
            bool ret = true;
            {
                if (Initialize())
                {
                    try
                    {
                        String fullPath = GetAdress(_pathString, type, pos, zoom + 1);
                        if (!File.Exists(fullPath))
                        {
                            string folderName = System.IO.Path.GetDirectoryName(fullPath);
                            if (!Directory.Exists(folderName))
                            {
                                Directory.CreateDirectory(folderName);
                            }
                            
                            File.WriteAllBytes(fullPath,tile.GetBuffer());
                        }
                    }
                    catch (Exception ex)
                    {
                        Debug.WriteLine(ex.ToString());
                        ret = false;
                        //Dispose();
                    }
                }
            }
            return ret;
        }

        public PureImage GetImageFromCache(MapType type, Point pos, int zoom)
        {
            PureImage ret = null;
            {
                if (Initialize())
                {
                    try
                    {
                        byte[] tile = (byte[])File.ReadAllBytes(GetAdress(_pathString, type, pos, zoom + 1));
                        MemoryStream stm = new MemoryStream(tile, 0, tile.Length, false, true);
                        ret = GMaps.Instance.ImageProxy.FromStream(stm);
                        if (ret != null)
                        {
                            ret.Data = stm;
                        }
                        tile = null;
                    }
                    catch (Exception ex)
                    {
                        Debug.WriteLine(ex.ToString());
                        ret = null;
                        //Dispose();
                    }
                }
            }
            return ret;
        }
        #endregion

        private String GetAdress(String pathString,MapType type, Point pos, int zoom)
        {
            //TODo: fix bug for zoom > 11
            return pathString + GetmapFolder(type) + Path.DirectorySeparatorChar + "z" + zoom +
                   Path.DirectorySeparatorChar + 0 + "x" +
                   pos.X + Path.DirectorySeparatorChar +
                   0 + Path.DirectorySeparatorChar + "y" + pos.Y + ".jpg";
        }

        private String GetmapFolder (MapType type)
        {
            string ret = String.Empty;
            switch (type)
            {
                case MapType.GoogleSatellite:
                    {
                        ret = "sat";
                        break; ;
                    }
                case MapType.GoogleHybrid:
                    {
                        ret = "both";
                        break;
                    }
                case MapType.GoogleMap:
                    {
                        ret = "map";
                        break;
                    }
                default:
                    {
                        ret = "UnknownMap";
                        break; ;
                    }
            }
            return ret;
        }
    }
}
